package svc

import (
	"time"

	"mall/service/attachment/rpc/attachmentclient"
	"mall/service/backend/api/internal/config"
	"mall/service/backend/api/internal/middleware"
	"mall/service/backend/common/gorseclient"
	"mall/service/backend/common/i18n"
	"mall/service/backend/common/utils/captcha"
	"mall/service/backend/rpc/backendclient"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/rpc/forumclient"
	"mall/service/order/rpc/orderclient"
	"mall/service/product/rpc/productclient"
	"mall/service/promotion/rpc/promotionclient"
	"mall/service/setting/rpc/settingclient"
	"mall/service/user/rpc/userclient"

	"github.com/casbin/casbin/v2"
	"github.com/elastic/go-elasticsearch/v7"
	"github.com/mojocn/base64Captcha"
	"github.com/silenceper/wechat/v2/miniprogram"
	"github.com/zeromicro/go-queue/kq"
	"github.com/zeromicro/go-zero/core/collection"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/redis"
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/zrpc"
)

type ServiceContext struct {
	Config config.Config

	BizRedis  *redis.Redis
	Trans     *i18n.Translator
	Validator *Validator
	Captcha   *base64Captcha.Captcha
	Casbin    *casbin.Enforcer
	Authority rest.Middleware

	LocalCache  *collection.Cache
	EsClient    *elasticsearch.Client
	MiniProgram *miniprogram.MiniProgram
	GorseClient gorseclient.GorseClient

	AttachmentRpc attachmentclient.Attachment
	BackendRpc    backendclient.Backend
	BlogRpc       blogclient.Blog
	ForumRpc      forumclient.Forum
	OrderRpc      orderclient.Order
	ProductRpc    productclient.Product
	PromotionRpc  promotionclient.Promotion
	SettingRpc    settingclient.Setting
	UserRpc       userclient.User

	CheckUri rest.Middleware

	KqDistributePointsClient *kq.Pusher
	KqCreateGorseItemClient  *kq.Pusher

	//todo
	KqDeferredUnFreezePointCouponClient *kq.Pusher
}

func NewServiceContext(c config.Config) *ServiceContext {
	localCache, err := collection.NewCache(time.Second * time.Duration(c.Query.LocalCacheExpireTime))
	logx.Must(err)

	esClient, _ := newElasticClient(c)
	// logx.Must(err)

	cbn := c.CasbinConf.MustNewCasbin(c.DatabaseConf.Type, c.DatabaseConf.GetDSN())
	// cbn := c.CasbinConf.MustNewCasbinWithRedisWatcher(c.DatabaseConf.Type, c.DatabaseConf.GetDSN(), c.BizRedis)

	rds := redis.MustNewRedis(c.BizRedis)

	var trans *i18n.Translator
	if len(c.I18nConf.Dir) > 0 {
		trans = i18n.NewTranslatorFromFile(c.I18nConf)
	} else {
		trans = i18n.NewTranslator(i18n.LocaleFS)
	}

	return &ServiceContext{
		Config: c,

		BizRedis:  rds,
		Trans:     trans,
		Validator: newValidator(),
		Captcha:   captcha.MustNewRedisCaptcha(c.Captcha, rds),
		Casbin:    cbn,
		Authority: middleware.NewAuthorityMiddleware(cbn, rds, trans).Handle,

		LocalCache:  localCache,
		EsClient:    esClient,
		MiniProgram: newMiniprogramClient(c),
		GorseClient: gorseclient.NewGorseClient(),

		AttachmentRpc: attachmentclient.NewAttachment(zrpc.MustNewClient(c.AttachmentRpc)),
		BackendRpc:    backendclient.NewBackend(zrpc.MustNewClient(c.BackendRpc)),
		BlogRpc:       blogclient.NewBlog(zrpc.MustNewClient(c.BlogRpc)),
		ForumRpc:      forumclient.NewForum(zrpc.MustNewClient(c.ForumRpc)),
		ProductRpc:    productclient.NewProduct(zrpc.MustNewClient(c.ProductRpc)),
		OrderRpc:      orderclient.NewOrder(zrpc.MustNewClient(c.OrderRpc)),
		PromotionRpc:  promotionclient.NewPromotion(zrpc.MustNewClient(c.PromotionRpc)),
		SettingRpc:    settingclient.NewSetting(zrpc.MustNewClient(c.SettingRpc)),
		UserRpc:       userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),

		CheckUri: middleware.NewCheckUriMiddleware(rds).Handle,

		KqDistributePointsClient: kq.NewPusher(
			c.KqDistributePointsConf.Brokers,
			c.KqDistributePointsConf.Topic,
		),
		KqCreateGorseItemClient: kq.NewPusher(
			c.KqCreateGorseItemConf.Brokers,
			c.KqCreateGorseItemConf.Topic,
		),

		//todo
		KqDeferredUnFreezePointCouponClient: kq.NewPusher(
			c.KqUnFreezePointCouponConf.Brokers,
			c.KqUnFreezePointCouponConf.Topic,
		),
	}
}
